require "lib.base"

local http = {}
local HEADER_KEY_METHOD = "method"
local HEADER_KEY_URL = "url"
local HEADER_KEY_SRC_URL = "src_url"
local HEADER_KEY_HTTP_VERSION = "http-version"
local HTTP_METHOD_GET   = 1
local HTTP_METHOD_POST  = 2
local http_methods = {
    GET =   HTTP_METHOD_GET,
    POST=   HTTP_METHOD_POST,
}

local header_base = {}

function header_base:get_url()
    return self.request[HEADER_KEY_URL]
end

function header_base:get_src_url()
    return self.request[HEADER_KEY_SRC_URL]
end

function header_base:get_method()
    return self.request[HEADER_KEY_METHOD]
end

function header_base:get_http_version()
    local http_version = self.request[HEADER_KEY_HTTP_VERSION]
    if http_version then
        return string.sub(http_version, string.find(http_version, "/")+1)
    end
end

function header_base:get_host()
    return self.request["Host"]
end

function header_base:full_url()
    return self:get_host()..self:get_src_url()
end

function header_base:get_user_agent()
    return self.request["User-Agent"]
end

function header_base:render_response_html(msg, status)
    status = status or 200
    self.response[1] = string.format("HTTP/1.1 %d OK", status)
    self.response[2] = "Server: esvr/0.1"
    self.response[3] = "Date: "..os.date("%a, %d %b %Y %X GMT")
    self.response[4] = "Content-Type: text/html; charset=utf-8"
    self.response[5] = "Content-Length: "..(string.len(msg)+2)
    self.response[6] = "Connection:close"
    self.response[7] = "\r\n"
    self.response[8] = msg
    return table.concat(self.response, "\r\n")
end

function header_base:render_response_404()
    self.response[1] = string.format("HTTP/1.1 %d Not Found", 404)
    self.response[2] = "Server: esvr/0.1"
    self.response[3] = "Last-Modified: "..os.date("%a, %d %b %Y %X GMT")
    self.response[4] = "Content-Type: text/html;charset=utf-8"
    self.response[5] = "Content-Length: 0"
    self.response[6] = "Connection: close"
    self.response[7] = "\r\n"
    return table.concat(self.response, "\r\n")
end

function header_base:render_response_text(msg, config)
    self.response[1] = "HTTP/1.1 200 OK"
    self.response[2] = "Date: "..os.date("%a, %d %b %Y %X GMT", os.time()-3600)
    self.response[3] = "Last-Modified :"..os.date("%a, %d %b %Y %X GMT", os.time() - 3600)
    self.response[4] = string.format("Content-Type: %s, charset=utf-8", config.content_type)
    self.response[5] = "Cache-Control: max-age=315360000"
    self.response[6] = "Expires: "..os.date("%a, %d %b %Y %X GMT", os.time() + 315360000)
    self.response[7] = "Server: esvr/0.1"
    self.response[8] = "Content-Length: "..(string.len(msg)+2)
    self.response[9] = "Connection: close"
    self.response[10] = "\r\n"
    self.response[11] = msg
    return table.concat(self.response, "\r\n")
end

function header_base:render_response_js(msg)
    return self:render_response_text(msg, {content_type="application/x-javascript"})
end

function header_base:render_response_css(msg)
    return self:render_response_text(msg, {content_type="text/css"})
end

http.parse_request = function(http_str)
    local oo = require "lib.oo"
    local http_header = oo.extends(header_base, {request={args={}}, response={}})
    local header = http_header.request
    lines = string.split(http_str, "\r\n")
    local start, from, to = 1, 1
    from, to= string.find(lines[1], "%s+", start)
    --parse method
    local method = string.sub(lines[1], 1, from - 1)
    if not http_methods[method] then
        method = method .. "NOTSUPPORT"
    end
    header[HEADER_KEY_METHOD] = method
    --parse http-version、url
    start = to + 1
    from, to= string.find(lines[1], "%s+", start)
    local url = string.sub(lines[1], start, from-1)
    local http_version = string.sub(lines[1], to + 1)
    header[HEADER_KEY_HTTP_VERSION] = http_version
    header[HEADER_KEY_SRC_URL] = url
    from, to = string.find(url, "%?")
    if from then
        params = string.sub(url, to + 1)
        url = string.sub(url, 1, from - 1)
        params = string.split(params, "&")
        for _, line in ipairs(params) do
            kv = string.split(line, "=")
            header.args[kv[1]] = kv[2]
        end
    end
	url = string.byte(url) == string.byte('/') and string.sub(url, 2) or url
    if not url or string.len(url) == 0 then
        url = "index"
    end
    header[HEADER_KEY_URL] = url
    --parse other fields
    for i = 2, #lines do
        from, to = string.find(lines[i], ":")
        if from then
            header[string.sub(lines[i], 1, from - 1)] = string.trim(string.sub(lines[i], to + 1))
        end
    end
    return http_header
end

return http
